package com.coalmine.api.controller;

import com.coalmine.api.annotation.LoginRequired;
import com.coalmine.api.domain.ApiConfig;
import com.coalmine.api.domain.ApiGroup;
import com.coalmine.api.domain.ApiStat;
import com.coalmine.api.domain.resp.ApiStatByTypeRespVO;
import com.coalmine.api.domain.resp.ApiStatRespVO;
import com.coalmine.api.domain.resp.ApiStatSummaryRespVO;
import com.coalmine.api.enums.EApiStatType;
import com.coalmine.api.service.IApiConfigService;
import com.coalmine.api.service.IApiGroupService;
import com.coalmine.api.service.IApiStatService;
import com.coalmine.common.constant.HttpStatus;
import com.coalmine.common.core.controller.BaseController;
import com.coalmine.common.core.domain.AjaxResult;
import com.coalmine.common.utils.DateUtils;
import com.coalmine.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 资源统计
 *
 * @author wangleibo
 * @since 2022-09-10
 */
@Slf4j
@Api(tags = "API-资源统计")
@RestController
@RequestMapping("/api/stat")
public class ApiStatController extends BaseController {

    @Autowired
    private IApiStatService apiStatService;

    @Autowired
    private IApiConfigService apiConfigService;

    @Autowired
    private IApiGroupService apiGroupService;

    @Autowired
    private HttpServletRequest request;

    @GetMapping("/summary")
    @ApiOperation("每日汇总统计")
    @LoginRequired(required = true)
    AjaxResult summary() {
        String token = request.getHeader("id");
        if (StringUtils.isEmpty(token)) {
            return new AjaxResult(HttpStatus.UNAUTHORIZED, "请登录后再操作！");
        }
        List<ApiStat> apiStatList = apiStatService.statByDay(DateUtils.dateTime());
        if (apiStatList.size() == 0) {
            return new AjaxResult(HttpStatus.SUCCESS, "暂无数据！");
        }
        // <groupId, groupName>
        List<ApiGroup> groupList = apiGroupService.getAll();
        Map<String, String> groupNameMap = groupList.stream()
                .collect(Collectors.toMap(ApiGroup::getId, ApiGroup::getName));

        // <apiId, apiName>
        List<String> apiIds = apiStatList.stream().map(ApiStat::getApiId).collect(Collectors.toList());
        List<ApiConfig> apiConfigList = apiConfigService.listByIds(apiIds);
        Map<String, String> apiNameMap = apiConfigList.stream()
                .collect(Collectors.toMap(ApiConfig::getId, ApiConfig::getName));
        Map<String, String> apiGroupMap = apiConfigList.stream()
                .collect(Collectors.toMap(ApiConfig::getId, ApiConfig::getGroupId));
        // <apiId, successTimes>
        Map<String, Long> statMap = new HashMap<>();
        for (ApiStat apiStat: apiStatList) {
            if (statMap.containsKey(apiStat.getApiId())) {
                statMap.put(apiStat.getApiId(), statMap.get(apiStat.getApiId()) + apiStat.getSuccessTimes());
                continue;
            }
            statMap.put(apiStat.getApiId(), apiStat.getSuccessTimes());
        }

        Map<String, List<ApiStatRespVO>> groupStatMap = new HashMap<>();
        statMap.forEach((api, stat) -> {
            List<ApiStatRespVO> apiStatRespVOList = new ArrayList<>();
            ApiStatRespVO respVO = new ApiStatRespVO();
            String apiName = apiNameMap.get(api);
            String groupName = null;
            if (apiGroupMap.containsKey(api)) {
                String groupId = apiGroupMap.get(api);
                groupName = groupNameMap.get(groupId);
            }
            respVO.setApiName(apiName);
            respVO.setSuccessTimes(stat);
            if (groupStatMap.containsKey(groupName)) {
                List<ApiStatRespVO> hisAddedList = groupStatMap.get(groupName);
                apiStatRespVOList.add(respVO);
                apiStatRespVOList.addAll(hisAddedList);
                groupStatMap.put(groupName, apiStatRespVOList);
            } else {
                apiStatRespVOList.add(respVO);
                groupStatMap.put(groupName, apiStatRespVOList);
            }
        });

        List<ApiStatSummaryRespVO> data = new ArrayList<>();
        groupStatMap.forEach((g, stat) -> {
            ApiStatSummaryRespVO respVO = new ApiStatSummaryRespVO();
            respVO.setGroupName(g);
            respVO.setApiStat(stat);
            respVO.setSuccessTimes(
                    stat.stream()
                    .map(ApiStatRespVO::getSuccessTimes)
                    .reduce(0L, Long::sum)
            );
            data.add(respVO);
        });

        return AjaxResult.success(data.stream()
                .sorted(Comparator.comparing(ApiStatSummaryRespVO::getSuccessTimes).reversed())
                .collect(Collectors.toList()));
    }

    @GetMapping("/byType")
    @ApiOperation("根据类型汇总")
    @LoginRequired(required = true)
    AjaxResult byType(@RequestParam EApiStatType type) {
        String token = request.getHeader("id");
        if (StringUtils.isEmpty(token)) {
            return new AjaxResult(HttpStatus.UNAUTHORIZED, "请登录后再操作！");
        }
        if (EApiStatType.DAY.getCode() == type.getCode()) {
            String startDay = DateUtils.parseDateToStr(DateUtils.YYYYMMDD,
                    DateUtils.addDays(DateUtils.getNowDate(), -30));
            String endDay = DateUtils.dateTime();
            List<ApiStat> apiStatList = apiStatService.statByDayRange(startDay, endDay);
            Map<String, List<ApiStat>> groupByDay = apiStatList.stream()
                    .collect(Collectors.groupingBy(ApiStat::getDay));
            List<ApiStatByTypeRespVO> data = new ArrayList<>();
            groupByDay.forEach((day, statList) -> {
                ApiStatByTypeRespVO respVO = new ApiStatByTypeRespVO();
                respVO.setDate(day);
                long successTimes = 0L;
                long failureTimes = 0L;
                for (ApiStat apiStat: statList) {
                    successTimes += apiStat.getSuccessTimes();
                    failureTimes += apiStat.getFailureTimes();
                }
                respVO.setSuccessTimes(successTimes);
                respVO.setFailureTimes(failureTimes);
                data.add(respVO);
            });
            List<String> currDayList = data.stream().map(ApiStatByTypeRespVO::getDate).collect(Collectors.toList());
            List<String> allDays = getDayList();
            allDays.removeAll(currDayList);
            if (allDays.size() > 0) {
                for (String day: allDays) {
                    ApiStatByTypeRespVO respVO = new ApiStatByTypeRespVO();
                    respVO.setDate(day);
                    respVO.setSuccessTimes(0);
                    respVO.setFailureTimes(0);
                    data.add(respVO);
                }
            }
            return new AjaxResult(HttpStatus.SUCCESS, "请求成功",
                    data.stream().sorted(Comparator.comparing(ApiStatByTypeRespVO::getDate).reversed()).collect(Collectors.toList()));
        }
        if (EApiStatType.MONTH.getCode() == type.getCode()) {
            List<ApiStat> apiStatList = apiStatService.statByMonth();
            Map<String, List<ApiStat>> groupByMonth = apiStatList.stream()
                    .collect(Collectors.groupingBy(ApiStat::getDay));
            List<ApiStatByTypeRespVO> data = new ArrayList<>();
            groupByMonth.forEach((month, statList) -> {
                ApiStatByTypeRespVO respVO = new ApiStatByTypeRespVO();
                respVO.setDate(month);
                long successTimes = 0L;
                long failureTimes = 0L;
                for (ApiStat apiStat: statList) {
                    successTimes += apiStat.getSuccessTimes();
                    failureTimes += apiStat.getFailureTimes();
                }
                respVO.setSuccessTimes(successTimes);
                respVO.setFailureTimes(failureTimes);
                data.add(respVO);
            });
            List<String> currMonthList = data.stream().map(ApiStatByTypeRespVO::getDate).collect(Collectors.toList());
            List<String> allMonth = getMonthList();
            allMonth.removeAll(currMonthList);
            if (allMonth.size() > 0) {
                for (String month: allMonth) {
                    ApiStatByTypeRespVO respVO = new ApiStatByTypeRespVO();
                    respVO.setDate(month);
                    respVO.setSuccessTimes(0);
                    respVO.setFailureTimes(0);
                    data.add(respVO);
                }
            }
            return new AjaxResult(HttpStatus.SUCCESS, "请求成功",
                    data.stream().sorted(Comparator.comparing(ApiStatByTypeRespVO::getDate).reversed()).collect(Collectors.toList()));
        }
        return new AjaxResult(HttpStatus.ERROR, "类型错误！");
    }

    private List<String> getDayList() {
        Calendar calendar = Calendar.getInstance();
        List<String> dayList = new ArrayList<>();
        for (int i = 0; i < 30; i++) {
            calendar.setTime(new Date());
            calendar.add(Calendar.DATE, -i);
            Date d = calendar.getTime();
            dayList.add(DateUtils.parseDateToStr(DateUtils.YYYYMMDD, d));
        }
        return dayList;
    }

    private List<String> getMonthList() {
        Calendar calendar = Calendar.getInstance();
        List<String> monthList = new ArrayList<>();
        for (int i = 0; i < 12; i++) {
            calendar.setTime(new Date());
            calendar.add(Calendar.MONTH, -i);
            Date d = calendar.getTime();
            monthList.add(DateUtils.parseDateToStr(DateUtils.YYYYMM, d));
        }
        return monthList;
    }
}
